package com.mspbots.web.core;


import cn.hutool.core.util.RandomUtil;
import com.mspbots.api.RestMessageObject;
import com.mspbots.api.client.CoreClient;
import com.mspbots.web.core.model.TeamsUser;
import com.mspbots.web.security.User;
import com.mspbots.web.security.service.AuthService;
import com.mspbots.web.security.service.UsersService;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * com.mspbots.web.core.TeamsMessageController
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/7/4
 */
@Log4j2
@RequiredArgsConstructor
@RestController
@RequestMapping(path = "/teamsweb")
public class TeamsController {

    private final CoreClient coreClient;
    private final PasswordEncoder passwordEncoder;
    private final UsersService usersService;

    @PostMapping(path = "/sender/{message}", consumes = "application/x-www-form-urlencoded")
    public Mono senderMessage(@PathVariable("message") String message,
                              @RequestParam("teamsUserId") String teamsUserId,
                              SenderMessageBody body) {
        return this.coreClient.post("/teams/user-message/" + message + "?teamsUserId=" + teamsUserId, body);
    }

    @PostMapping(path = "/sender")
    public Mono recordMessage(@RequestBody Map map) {
        return this.coreClient.post("/teams/user-message/", map);
    }

    @GetMapping(path = "/message/page")
    public Mono selectPage(@RequestParam Map<String, Object> params) {
        return this.coreClient.get("/teams/user-message/page", params);
    }

    @PostMapping(path = "/user/add-batch/{tenantId}")
    public Mono saveBatchUsers(@PathVariable Long tenantId, @RequestBody List<TeamsUser> users) {
//        return Mono.fromRunnable(() ->
//                        this.coreClient.postFlux("/teams/user/add-batch/" + tenantId, users, TeamsUser.class)
//                                .subscribe()
//        ).map(m -> RestMessageObject.ok("Teams user add batch success."));
                        /*users.parallelStream().forEach(tu -> {
                            User user = User.builder().username(tu.getTeamsMail().toLowerCase())
                                    .password(this.passwordEncoder.encode(RandomUtil.randomString(6)))
                                    .roles(Set.of(AuthService.DEFAULT_TENANT_USER_ROLE_NAME))
                                    .email(tu.getTeamsMail().toLowerCase())
                                    .enabled(true)
                                    .tenantId(tu.getTenantId())
                                    .build();
                            String[] userName = StringUtils.split(tu.getTeamsDisplayName(), " ");
                            if (!ObjectUtils.isEmpty(userName)) {
                                user.setFirstName(userName[0]);
                                user.setLastName(userName[1]);
                            }
                            this.usersService.loadUser(user.getUsername())
                                    .switchIfEmpty(this.usersService.save(user))
                                    .flatMap(u-> this.usersService.save(user))
                                    .flatMap(user1 -> )
                                        .subscribe(u -> tu.setUserId(u.getId())
                                        );
                        });*/
                    /*Flux.fromIterable(users).filter(tu -> !StringUtils.isEmpty(tu.getTeamsMail()) && !tu.getTeamsMail().contains("#EXT#"))
                            .doOnNext(tu -> {
                                User user = User.builder().username(tu.getTeamsMail().toLowerCase())
                                        .password(this.passwordEncoder.encode(RandomUtil.randomString(6)))
                                        .roles(Set.of(AuthService.DEFAULT_TENANT_USER_ROLE_NAME))
                                        .email(tu.getTeamsMail().toLowerCase())
                                        .enabled(true)
                                        .tenantId(tu.getTenantId())
                                        .build();
                                String[] userName = StringUtils.split(tu.getTeamsDisplayName(), " ");
                                if (!ObjectUtils.isEmpty(userName)) {
                                    user.setFirstName(userName[0]);
                                    user.setLastName(userName[1]);
                                }
                                this.usersService.loadUser(user.getUsername())
                                        .switchIfEmpty(this.usersService.save(user))
                                        .flatMap(u-> this.usersService.save(user));
//                                        .subscribe(u -> tu.setUserId(u.getId())
//                                        );

                            }).collectList()
                            .subscribe(teamsUsers-> this.coreClient.postFlux("/teams/user/add-batch/" + tenantId, teamsUsers, TeamsUser.class).subscribe()))
            .map(m -> RestMessageObject.ok("Teams user add batch success."));*/
        return Mono.fromRunnable(() -> this.coreClient.postFlux("/teams/user/add-batch/" + tenantId, users, TeamsUser.class)
                .filter(tu -> !StringUtils.isEmpty(tu.getTeamsMail()) && !tu.getTeamsMail().contains("#EXT#"))
                .map(tu -> {
                    User user = User.builder().username(tu.getTeamsMail().toLowerCase())
                            .password(this.passwordEncoder.encode(RandomUtil.randomString(6)))
                            .roles(Set.of(AuthService.DEFAULT_TENANT_USER_ROLE_NAME))
                            .email(tu.getTeamsMail().toLowerCase())
                            .enabled(true)
                            .tenantId(tu.getTenantId())
                            .build();
                    String[] userName = StringUtils.split(tu.getTeamsDisplayName(), " ");
                    if (!ObjectUtils.isEmpty(userName)) {
                        user.setFirstName(userName[0]);
                        user.setLastName(userName[1]);
                    }
                    return user;
                })
                .subscribe(user -> this.usersService.loadUser(user.getUsername())
                        .switchIfEmpty(this.usersService.save(user))
//                                .flatMap(u-> this.usersService.save(user))
//                                .map(item->  Map.of("userName", item.getEmail(), "action","new"))
                        .subscribe(u -> log.debug("Teams sync user and register security user by {}", u),
//                                .subscribe(powerBIUser ->
////                    rabbitTemplate.convertAndSend(POWERBI_EXCHANGE_NAME, USERS_SYNC_QUEUE, powerBIUser),
                                ex -> log.error("Teams sync user and register security user is error.msg:{}",
                                        ex.getMessage())
                        )))
                .map(m -> RestMessageObject.ok("Teams user add batch success."));
    }

    @Data
    @NoArgsConstructor
    public static class SenderMessageBody {
        private String teamsUserId;
        private String reason;
        private String time;
        private LocalDateTime logTime;
        private Integer duration;
        private Integer fromType;
        private Boolean check;

        @Builder
        public SenderMessageBody(String teamsUserId, String reason, String time, LocalDateTime logTime, Integer duration, Boolean check) {
            this.teamsUserId = teamsUserId;
            this.reason = reason;
            this.time = time;
            this.logTime = logTime;
            this.duration = duration;
            this.check = check;
        }
    }
}
